﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BLL;
using WcfServices.ServiceInterfaces;
using EntitiesLayer;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Data.SqlClient;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.IO;
using System.Reflection;
using System.Text;
using System.Globalization;
using System.Drawing;
using System.Drawing.Imaging;


namespace WcfServices.Utilities
{
    public static class Util
    {
        public static T interceptWithReturn<T>(Func<T> funcion) where T:class {

            WebOperationContext contexto = WebOperationContext.Current;

            try
            {

                T elemento = funcion();

                if (elemento == null)
                    contexto.OutgoingResponse.StatusCode = HttpStatusCode.NoContent;

                return elemento;
            }
            catch (SqlException ex)
            {

                bool hayConcexion=true;
                for (int i=0; (i<ex.Errors.Count) && hayConcexion; i++)
                    hayConcexion = !(ex.Errors[i].Number == 11001 
                                     || ex.Errors[i].Number== 121
                                     || ex.Errors[i].Number==10061
                                     || ex.Errors[i].Number==10060);

                //error que no deberia ocurrir, se tira una excepcion para debugear
                if (hayConcexion)
                    throw ex;

                //hay un error de coneccion por lo tanto se establece el status code 503
                contexto.OutgoingResponse.StatusCode = HttpStatusCode.ServiceUnavailable;
                

            }


            return null;
        
        }
        public static void interceptWithNoReturn(Action action)
        {
            WebOperationContext contexto = WebOperationContext.Current;

            try
            {
                action();
            }
            catch (SqlException ex)
            {

                //solo se checkea el primer error. 
                switch (ex.Errors[0].Number)
                {

                    case 11001:
                    case 121:
                    case 10061:
                        contexto.OutgoingResponse.StatusCode = HttpStatusCode.ServiceUnavailable;

                        break;
                    //agregar mas
                    default:

                        throw ex;

                }

            }
        }
        public static string ReadToString(this Stream stream){

            using (StreamReader reader = new StreamReader(stream)) {

                return reader.ReadToEnd();
            }
        }
        public static T DeserializeJson<T>(this Stream stream){
            
            JsonSerializer s = new JsonSerializer();
            
            using (StreamReader reader = new StreamReader(stream)) 
            using (var jsonReader = new JsonTextReader(reader))
                return s.Deserialize<T>(jsonReader);
            
        }

        

        public static string JsonSerialize<T>(this T objeto ,Type[] ignoreTypes=null, 
            string[] ignorePropertie=null, JsonConverter[]conveters =null){

            if (objeto == null)
                throw new NullReferenceException();

             var jsonResolver = new IgnorableSerializerContractResolver();
                
               for (int i=0 ; ignoreTypes!=null && i<ignoreTypes.Length; i++)
                   jsonResolver.Ignore(ignoreTypes[i]);
               
               for (int i=0 ; ignorePropertie!=null && i<ignorePropertie.Length; i++)
                   jsonResolver.Ignore(ignorePropertie[i]);
                

                var jsonSettings = new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                    ContractResolver = jsonResolver
                };


                JsonSerializer serializer= JsonSerializer.Create(jsonSettings);

                for (int i = 0; conveters != null && i < conveters.Length;i++ )
                    serializer.Converters.Add(conveters[i]);
                    
                 return serializer.StringSerialize(objeto);   

                    
        }
        public static string StringSerialize<T>(this JsonSerializer serializer, T objeto) {

            using (var writer = new StringWriter())
            {
                using (var jsonWriter = new JsonTextWriter(writer))
                {
                    serializer.Serialize(jsonWriter, objeto);

                    return writer.ToString();

                }
            }
        }
        public static string[] GetPropertiesOfType(this Type type, Type type2){

            PropertyInfo[] properties = type.GetProperties();

            IList<string> names= new List<string>();
            foreach (PropertyInfo pinfo in properties)
            {
                Type p = pinfo.PropertyType;
                if (p.IsGenericType && p.GetGenericTypeDefinition() == type)
                    names.Add(pinfo.Name);
            }
            return names.ToArray();
        }
        public static byte[] ToImageByte(this string base64)
        {

            Byte[] bitmapData = new Byte[base64.Length];

            bitmapData = Convert.FromBase64String(FixBase64ForImage(base64));

            return bitmapData;


        }
        private static string FixBase64ForImage(string Image)
        {
            StringBuilder sbText = new System.Text.StringBuilder(Image, Image.Length);

            sbText.Replace("\r\n", String.Empty);
            sbText.Replace(" ", String.Empty);

            return sbText.ToString();
        }

    

        public static DateTime ToGlobalDateAplicationFormat(this string date) { 
            
            //Formato global de la fecha
             const string FORMAT= "dd/MM/yyyy";
            
            try{
                return DateTime.ParseExact(date, FORMAT, CultureInfo.InvariantCulture);
            }catch (FormatException ex) {
                WebOperationContext contexto = WebOperationContext.Current;

                //error 403
                contexto.OutgoingResponse.StatusCode = HttpStatusCode.Forbidden;

                throw ex;

            }
        
        }

    }
        
}
    


